package com.guosen.zebra.framework.starter.sms.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.guosen.zebra.framework.starter.sms.config.SmsProperties;
import com.guosen.zebra.framework.starter.sms.enums.SmsApis;
import com.guosen.zebra.framework.starter.sms.exception.SmsException;
import com.guosen.zebra.framework.starter.sms.internal.SmsHttpClient;
import com.guosen.zebra.framework.starter.sms.model.international.SmsInternationalPrefixResponse;
import com.guosen.zebra.framework.starter.sms.model.status.SmsStatusInfoResponse;
import com.guosen.zebra.framework.starter.sms.model.upsms.UpSmsInfoResponse;
import com.guosen.zebra.framework.starter.sms.service.SmsQueryService;
import com.guosen.zebra.framework.starter.sms.utils.JsonUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

import static com.guosen.zebra.framework.starter.sms.constants.SmsExceptionMessage.*;
import static com.guosen.zebra.framework.starter.sms.constants.SmsFields.*;

/**
 * SMS查询服务实现
 */
@Slf4j
public class SmsQueryServiceImpl implements SmsQueryService {

    private final SmsProperties smsProperties;

    public SmsQueryServiceImpl(SmsProperties smsProperties) {
        this.smsProperties = smsProperties;
    }

    @Override
    public SmsInternationalPrefixResponse queryInternationalPrefix() {
        String url = smsProperties.getAddress() + SmsApis.GET_INTERNATIONAL_PREFIX_LIST.getApi();
        JsonNode result;
        try {
            result = SmsHttpClient.post(url, addToken(new HashMap<>()));
        } catch (SmsException e) {
            log.error("[SMS] query international prefix is failed, error message:{}", e.getMessage());
            throw new SmsException(QUERY_INTERNATIONAL_PREFIX_FAILED, e);
        }
        try {
            return JsonUtil.getObjectMapper().treeToValue(result, SmsInternationalPrefixResponse.class);
        } catch (JsonProcessingException e) {
            log.error("[SMS] international prefix response resolving is failed, error message:{}", e.getMessage());
            throw new SmsException(RESPONSE_RESOLVE_FAILED + result, e);
        }
    }

    @Override
    public SmsStatusInfoResponse querySmsStatusInfo(String smsId) {
        String url = smsProperties.getAddress() + SmsApis.GET_SMS_STATUS.getApi();
        JsonNode result;
        Map<String, String> formData = buildSmsStatusQueryMap(smsId);
        try {
            result = SmsHttpClient.post(url, formData);
        } catch (SmsException e) {
            log.error("[SMS] query sms status info is failed, smsId: {}, error message:{}", smsId, e.getMessage());
            throw new SmsException(QUERY_SMS_STATUS_FAILED, e);
        }
        try {
            return JsonUtil.getObjectMapper().treeToValue(result, SmsStatusInfoResponse.class);
        } catch (JsonProcessingException e) {
            log.error("[SMS] sms status response resolving is failed, smsId: {}, error message:{}", smsId, e.getMessage());
            throw new SmsException(RESPONSE_RESOLVE_FAILED + result, e);
        }
    }

    @Override
    public UpSmsInfoResponse queryUpSmsInfo(String mobile) {
        String url = smsProperties.getAddress() + SmsApis.GET_UP_SMS_BY_MOBILE.getApi();
        JsonNode result;
        Map<String, String> formData = buildUpSmsQueryMap(mobile);
        try {
            result = SmsHttpClient.post(url, formData);
        } catch (SmsException e) {
            log.error("[SMS] query up sms info is failed, mobile: {}, error message: {}", mobile, e.getMessage());
            throw new SmsException(QUERY_UP_SMS_FAILED, e);
        }
        try {
            return JsonUtil.getObjectMapper().treeToValue(result, UpSmsInfoResponse.class);
        } catch (JsonProcessingException e) {
            log.error("[SMS] up sms response resolving is failed, mobile: {}, error message: {}", mobile, e.getMessage());
            throw new SmsException(RESPONSE_RESOLVE_FAILED + result, e);
        }
    }

    private Map<String, String> buildSmsStatusQueryMap(String smsId) {
        Map<String, String> formData = new HashMap<>();
        formData.put(SMS_ID, smsId);
        return addToken(formData);
    }

    private Map<String, String> buildUpSmsQueryMap(String mobile) {
        Map<String, String> formData = new HashMap<>();
        formData.put(MOBILE, mobile);
        return addToken(formData);
    }

    private Map<String, String> addToken(Map<String, String> map) {
        map.computeIfAbsent(TOKEN, key -> Optional.ofNullable(smsProperties.getToken()).orElse(""));
        return map;
    }
}
